#!/usr/bin/env node
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';

// 获取当前脚本的目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 配置
export const CHANGELOG_PATH = path.join(__dirname, '../CHANGELOG.md');
export const PACKAGE_JSON_PATH = path.join(__dirname, '../package.json');

// 读取版本信息
export async function readVersions() {
  // 读取文档版本
  const changelogContent = await fs.readFile(CHANGELOG_PATH, 'utf8');
  const docVersionMatch = changelogContent.match(/Document Version: (\d+\.\d+\.\d+)/);
  
  if (!docVersionMatch) {
    throw new Error('无法从变更日志中读取文档版本');
  }
  
  const docVersion = docVersionMatch[1];
  
  // 读取项目版本
  const packageJsonContent = await fs.readFile(PACKAGE_JSON_PATH, 'utf8');
  const packageJson = JSON.parse(packageJsonContent);
  const projectVersion = packageJson.version;
  
  return { docVersion, projectVersion };
}

// 生成唯一代码
export function generateUniqueCode() {
  const now = new Date();
  const datePart = now.getFullYear().toString().slice(2) + 
                  padZero(now.getMonth() + 1) + 
                  padZero(now.getDate());
  
  const randomPart = Math.random().toString(36).substr(2, 3).toUpperCase();
  
  return `${datePart}${randomPart}`;
}

// 生成变更日志条目
export function generateChangelogEntry(options, projectVersion, uniqueCode) {
  const now = new Date();
  const date = `${now.getFullYear()}-${padZero(now.getMonth() + 1)}-${padZero(now.getDate())}`;
  
  // 使用传入的项目版本号
  let entry = `## [${projectVersion}] - ${date} (${uniqueCode})\n\n`;
  
  if (options.changes && options.changes.length > 0) {
    entry += "### 更改\n";
    options.changes.forEach(change => {
      entry += `- ${change}\n`;
    });
    entry += "\n";
  }
  
  if (options.additions && options.additions.length > 0) {
    entry += "### 新增\n";
    options.additions.forEach(add => {
      entry += `- ${add}\n`;
    });
    entry += "\n";
  }
  
  if (options.deprecations && options.deprecations.length > 0) {
    entry += "### ~~已废弃~~\n";
    options.deprecations.forEach(deprecate => {
      entry += `- ${deprecate}\n`;
    });
    entry += "\n";
  }
  
  if (options.fixes && options.fixes.length > 0) {
    entry += "### 修复\n";
    options.fixes.forEach(fix => {
      entry += `- ${fix}\n`;
    });
    entry += "\n";
  }
  
  if (options.removals && options.removals.length > 0) {
    entry += "### 移除\n";
    options.removals.forEach(remove => {
      entry += `- ${remove}\n`;
    });
    entry += "\n";
  }
  
  if (options.security && options.security.length > 0) {
    entry += "### 安全\n";
    options.security.forEach(security => {
      entry += `- ${security}\n`;
    });
    entry += "\n";
  }
  
  return entry;
}

// 更新变更日志
export async function updateChangelog(entry) {
  let content = await fs.readFile(CHANGELOG_PATH, 'utf8');
  
  // 找到第一个版本条目
  const firstVersionRegex = /## \[[^\]]+\]([\s\S]*?)(?=## \[|\Z)/;
  const match = content.match(firstVersionRegex);
  
  if (match) {
    const insertPosition = match.index;
    content = content.slice(0, insertPosition) + entry + content.slice(insertPosition);
  } else {
    // 找到文档和项目版本信息之后的位置
    const versionInfoRegex = /Project Version: (\d+\.\d+\.\d+)/;
    const versionMatch = content.match(versionInfoRegex);
    
    if (versionMatch) {
      // 在版本信息之后插入新条目，保留标题和介绍
      const insertPosition = versionMatch.index + versionMatch[0].length + 1;
      content = content.slice(0, insertPosition) + "\n\n" + entry + content.slice(insertPosition);
    } else {
      // 如果找不到版本信息，则添加到文件末尾
      content = content + "\n\n" + entry;
    }
  }
  
  await fs.writeFile(CHANGELOG_PATH, content, 'utf8');
}

// 增加补丁版本号
export function incrementPatchVersion(version) {
  const [major, minor, patch] = version.split('.').map(Number);
  return `${major}.${minor}.${patch + 1}`;
}

// 更新文档版本
export async function updateDocVersion(newVersion) {
  let content = await fs.readFile(CHANGELOG_PATH, 'utf8');
  
  // 更新文档版本
  content = content.replace(
    /Document Version: (\d+\.\d+\.\d+)/, 
    `Document Version: ${newVersion}`
  );
  
  // 更新项目版本
  const { projectVersion } = await readVersions();
  content = content.replace(
    /Project Version: (\d+\.\d+\.\d+)/, 
    `Project Version: ${projectVersion}`
  );
  
  await fs.writeFile(CHANGELOG_PATH, content, 'utf8');
}

// 工具函数：补零
export function padZero(num) {
  return num < 10 ? `0${num}` : num;
}

// 解析命令行参数（简化版，只处理单个选项）
export function parseArgs(args, optionType) {
  // 如果没有参数，返回空数组
  if (args.length === 0) {
    return [];
  }
  
  const result = [];
  
  // 检查是否有直接传递的描述参数（不带选项标志）
  if (args.length > 0 && !args[0].startsWith('-')) {
    result.push(args[0]);
    args = args.slice(1); // 移除已处理的参数
  }
  
  // 处理npm传递的特殊情况：当命令是 npm run dp-xxx "描述" 时
  // npm可能会将参数传递为 ["描述"] 或者 ["--option=描述"]
  if (args.length === 1 && args[0].includes('=')) {
    const [flag, value] = args[0].split('=');
    if (flag === optionType.short || flag === optionType.long) {
      result.push(value);
    }
    return result;
  }
  
  let i = 0;
  while (i < args.length) {
    const arg = args[i];
    
    // 处理 -x=value 格式的参数
    if (arg.includes('=') && arg.startsWith('-')) {
      const [flag, value] = arg.split('=');
      if (flag === optionType.short || flag === optionType.long) {
        result.push(value);
      }
      i++;
      continue;
    }
    
    // 处理 -x value 格式的参数
    if (arg === optionType.short || arg === optionType.long) {
      if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
        result.push(args[i + 1]);
        i += 2;
      } else {
        console.error(`错误: ${optionType.short}/${optionType.long} 选项需要一个参数`);
        process.exit(1);
      }
    } else {
      i++;
    }
  }
  
  return result;
}

// 打印帮助信息
export function printHelp(scriptName, optionType) {
  console.log(`
使用方法: npm run ${scriptName} [选项] [描述]

选项:
  ${optionType.short}, ${optionType.long} "描述"    ${optionType.description}
  -h, --help               显示此帮助信息

示例:
  npm run ${scriptName} "这是一个描述"
  npm run ${scriptName} ${optionType.short} "这是一个描述"
  npm run ${scriptName} ${optionType.long}="这是一个描述"

此命令会自动:
  1. 生成唯一的六位变更码
  2. 更新变更日志，添加新条目
  3. 自增文档版本的修正号
  4. 同步项目版本到变更日志
`);
}

// 处理变更的通用函数
export async function processChanges(descriptions, optionType) {
  try {
    if (descriptions.length === 0) {
      console.error(`错误: 请提供${optionType.description}描述`);
      printHelp(optionType.scriptName, optionType);
      process.exit(1);
    }
    
    // 读取当前版本
    const { docVersion, projectVersion } = await readVersions();
    
    // 生成唯一代码
    const uniqueCode = generateUniqueCode();
    
    // 准备变更日志条目
    const options = {};
    options[optionType.optionKey] = descriptions;
    
    const entry = generateChangelogEntry(options, projectVersion, uniqueCode);
    
    // 更新变更日志
    await updateChangelog(entry);
    
    // 增加文档版本
    const newDocVersion = incrementPatchVersion(docVersion);
    await updateDocVersion(newDocVersion);
    
    console.log(`\n✅ 变更日志已更新至版本 ${newDocVersion}`);
    console.log(`   项目版本: ${projectVersion}`);
    console.log(`   变更代码: ${uniqueCode}`);
    console.log(`   ${optionType.description}:`);
    descriptions.forEach(desc => {
      console.log(`   - ${desc}`);
    });
    
  } catch (error) {
    console.error(`\n❌ 操作失败: ${error.message}`);
    process.exit(1);
  }
}